#ifndef TROYGLVIEW_H
#define TROYGLVIEW_H

#include "global.h"

#include <QStack>

#include "opengldisplay.h"
#include "troy.h"
#include "troyglcontroller.h"
#include "robotvisitor.h"

/**
 * @brief Displays Troy as an openGL wireframe.  Inherits OpenGLDisplay.
 *
*/
class TroyGLView : public OpenGLDisplay
{

public:
    enum ViewOption{
        FRONT,
        LEFT_SIDE,
        RIGHT_SIDE,
        THREE_QUARTER
    };

    TroyGLView(QWidget *parent = 0);

    virtual void loadController(RobotGLController *controller);

    //Re-implemented from the parent class to extend and customize functionality.
    //Specifically, the TroyGLView only allows for one component to be selected
    //at a time.
    virtual GUIComponent* selectComponent(NameGroup names);
    virtual void deselectComponent(NameGroup names);
    virtual void clearSelection();

    void setView(ViewOption option);

    void allowEditing(bool allowed);

protected:
    virtual void drawScene();
    virtual void initComponents();
    virtual void resizeGL(int width, int height);
    virtual void setPerspective(int width, int height);

private:
    //Matrix for shadow calculation.  This only needs to be computed once,
    //so we cache it.
    GLfloat shadowMat[4][4];

    /**
     * @brief A robot visitor that creates a GUIComponent
     * for each RobotComponent.
     *
     * Call components() to retrieve the components
     * after visiting.
    */
    class GUIComponentCreator : public RobotVisitor{
    public:
        void pre(){}
        void visit(RobotComponent *component);
        void post(){}
        QList<GUIComponent*> components();
    private:
        QList<GUIComponent*> _components;
    };

    /**
     * @brief A robot visitor that draws a robot in
     * openGL
     *
    */
    class RobotGLDrawer : public RobotVisitor{
    public:
        explicit RobotGLDrawer(GUIComponent* selected);
        void pre();
        void visit(RobotComponent *component);
        void post();
    private:
        GUIComponent* _selected;
    };

    //A pointer to the currently selected component
    GUIComponent* _selected;
    ViewOption _curView;

    //Helper function that draws the robot model
    void drawRobot();
    void drawFloor();

};

#endif // TROYGLVIEW_H
